//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
//

#ifndef SCE_H_
#define SCE_H_
#include <map>
#include "Signal_m.h"

using namespace std;


class SCE: public cSimpleModule
{
public:
	typedef map<int,L1vpnReq*> L1vpnMap;
	typedef map<int,link_state> MatrixMap;
	struct treeNode
	{
	    int nodeId; 			//nodeId in the whole topo
	    int gatewayth;			//the gateway id.
	    int nodeth;				//the turn of tree
	    treeNode *father;		//the father node
	    treeNode *firstSibling;	//the first sibling node
	    int bandwidth;			//the bandwidth from this node to father node
	};

	typedef map<int,treeNode> treeNodeMap;//store one tree by each node, so it is a map of node.
	typedef map<int,treeNodeMap> treeMap;//store all trees be the l1vpn request, it is a map of tree


	L1vpnMap mL1vpnMap;//the map to store L1vpn
	MatrixMap mMatrixMap;//the map to store the adjacent matrix,which used to compute l1vpn tree.
	treeMap mTreeMap;//the map to store l1vpn tree

protected:
	static void initAbstract();
	virtual void initialize();
	/*
	 * the default function of omnet,do some initialization work.
	 */
	virtual void handleMessage(cMessage *msg);
	/*
	 * the default function of omnet. handle the message
	 *  which from the node it self, the cp(control plane) node and remote SCE nodes.
	 */
    virtual void analyzeL1vpnRequest(L1vpnReq *pL1vpnReq);
	/*
	 * analyze the l1vpn request from cp node and
	 * the result is a vpn topo(tree or ring or other ..)
	 * All the policies and algorithms are added in this function.
	 * If the vpn topo is a tree,send the LSP by each branch of tree.
	 * If the vpn topo is a ring, send the LSP by each section of ring.
	 *
	 */
    virtual void processService(L1vpnReq *pL1vpnReq);
    /*
     * process the l1vpn topo which analyzed by the analyzeServiceRequest();
     * send the lsp req to local cp node or remote SCEs.
     */
    virtual LSPSignal* generateLSPReq(int srcAddr,int sinkAddr,int reqType,int bandwidth,L1vpnReq *pL1vpnReq,int id);
    /*
     * generate LSP request according to l1vpn tree
     */
    virtual void forwardLSPReq(LSPSignal* pLSPSignal);
    /*
	 *  When SCE receive the LSP req from remote SCE,
	 *  It will forward the LSP  Req  to the local cp node.
	 */

    virtual void updateL1vpnReq(L1vpnReq *pL1vpnReq,LSPSignal *pLSPSignal);
    /*
     * When receive the LSP result, update L1vpn Req according to LSP RESULT.
     */
    virtual void forwardRouteSignal(routeSignal *pRouteSignal);

    virtual void updateMatrix(routeSignal *pRouteSignal);

    virtual void topologyAbstract();
    /*
     * Abstract the topology in the domain layer(second layer).
     * There are many policies can be used to abstract topology of multi-domains.
     * Such as :
     * 1/Abstract the topology by the gataway node.
     * 2/Abstract each domain as one node.
     * 3/etc...
     */
    virtual void generateAndSendRouteReq(int srcAddr,int sinkAddr,int reqType,int SCENodeId,int lineNum,int rowNum,int L1vpnId);
    /*
     *
     */
    virtual void createNewMatrix(L1vpnReq *pL1vpnReq);
    /*
     * When receive L1vpn Request, we need a new topology to computing the l1vpn tree.
     * so we add the all endpoints of l1vpn into the matrix.
     */
    virtual void updateTree(treeNodeMap *pTree);
    /*
     * update the tree, delete the leaf which is not the endpoint.
     */
    virtual int caculateLinkRes(treeNodeMap *pTree);
    /*
     * Calculating the link resource and the cost of l1vpn tree.
     */
    void initWavelength(int fromNode, int toNode);
    /*
     * initialize the wavelength resource of each link.
     */
    void bfs(link_state *adj,int lineSize,int rowSize,treeNodeMap *pTree,int start);
    /*
     * Find the l1vpn tree whose root is "start" by breadth first search algorithm
     *
     */
private:
	 explicit_route routeTable;
	 link_state abstractAdjacentMatrix[GATEWAY_NUM][GATEWAY_NUM];    //the abstract topology
 //    link_state tempAdjacentMatrix[_NUM+MAX_ENDPOINT_NUM][NODE_NUM+MAX_ENDPOINT_NUM];    //the abstract topology by adding the endpoints

public:
	 int localSCEId;		//store the id of local SCE.
	 int localDomainId;     //the domain ID of SCE.
	 static double totalL1vpnReqNum;		//the total number of l1vpn request.
	 static double totalL1vpnBlockedNum;	//the total number of blocked l1vpn.

public:
	SCE();
	virtual ~SCE();
};

Define_Module(SCE);
#endif /* SCE_H_ */
